<template>
  <div class="route-design-wrapper">
    <div class="route-design">
      <div class="header">
        <i class="iconfont metro-lujingguihua"></i>
        <span>路径规划</span>
        <button class="start-btn" @click="enterDesign">
          {{ isDesign ? '离开规划模式' : '进入规划模式' }}
        </button>
      </div>
      <div class="content">
        <div>
          <span style="margin-right: 5px">起点:</span>
          <a-cascader v-model:value="startStation" :options="options" placeholder="请输入起点站">
            <template #clearIcon>
              <i class="iconfont metro-close"></i>
            </template>
          </a-cascader>
          <!-- <a-button style="margin-left: 8px" @click="pickStation('origin')">拾取起点站</a-button> -->
        </div>
        <div>
          <span style="margin-right: 5px">终点:</span>
          <a-cascader v-model:value="endStation" :options="options" placeholder="请输入终点站"
            ><template #clearIcon>
              <i class="iconfont metro-close"></i>
            </template>
          </a-cascader>
        </div>
      </div>
    </div>
  </div>
  <!-- 路径规划展示面板 -->
  <PathDesignDisplayCard :routeInfo="routeInfo" v-if="isDesign" :cacheData="cacheData" />
</template>

<script setup>
import { ref, onMounted, watch, onBeforeUnmount } from 'vue';
import { message } from 'ant-design-vue';
import { useLineData,hideStationByName,changeDisplayBillBoard } from '@/store';
import PathDesignDisplayCard from './PathDesignDisplayCard.vue';
import { getLinePlan } from '@/api/line.js';
import { flyToDefaultView, removeByCacheData, renderStation, renderLines, renderStationBill } from '@/cesiumTools/effectController';
import { lineColors } from '@/store/staticData';

let viewer;
const lineData = useLineData();
const subLineData = ref([]); //地铁线路数据
const startStation = ref([]); // 起点站
const endStation = ref([]); // 终点站
const isDesign = ref(false); // 是否处于路径规划模式
const routeInfo = ref({});
let pathInfo = {}; // 调用getLinePlan接口返回的路径规划数据
//路径规划实体数据
const cacheData = {
  lineEnts: [],
  stationEnts: [],
  billboards: [],
};

// 渲染下拉列表的数据
let options = ref([]);
onMounted(() => {
  viewer = lineData.Viewer;
  subLineData.value = lineData.allData;
  if (subLineData.value.length > 0) {
    options.value = subLineData.value.map(item => {
      const { name, stationsList } = item;
      const children = stationsList.map(s => ({
        value: s.name,
        label: s.name,
      }));
      return {
        label: name,
        value: name,
        children,
      };
    });
  }
});
// 组件销毁时，设置离开路径规划模式
onBeforeUnmount(() => {
  leaveRouteDesign();
});

watch([startStation, endStation], async value => {
  if (isDesign.value) {
    const data = await getLineData();
    pathInfo = data;
    // console.log('pathInfo', pathInfo);
    mapChange();
  }
});

const getLineData = async () => {
  const start = startStation.value;
  const end = endStation.value;
  //   console.log(start, 'start');
  //如果起点和终点都填入了数据，就跑服务，获取路径规划数据
  if (start.length && end.length) {
    let params = {};
    // 从lineData中获取坐标信息
    params.origin = getPositon(start[0], start[1]); // 起点
    params.destination = getPositon(end[0], end[1]); // 终点
    const { code, data } = await getLinePlan(params);
    // console.log('data', data);
    if (code === 200) {
      return data;
    } else {
      message.warn('查询不到相关数据');
      return null;
    }
  }
};

const getPositon = (lineName, stationName) => {
  const targetLine = subLineData.value.find(l => l.name === lineName);
  const { position } = targetLine.stationsList.find(s => s.name === stationName);
  //   console.log(position, 'position');
  return `${position.lng},${position.lat}`;
};

//根据数据，渲染站点站线，同时需要注意处理换乘站逻辑
const mapChange = () => {
  // 清除之前的道路规划实体
  removeActiveEnts();
  // 定义用于存储站点和路径数据的数组
  const stations = []; //存储渲染的站点信息
  const paths = []; //存储渲染的路径信息, 路径数据包含线路名称，站点序号，线路的坐标数据
  // 初始化一个route对象用于存储路径信息,route数据中包含线路总距离和站点信息
  const route = {
    stations: [], // 存储路径中的站点信息
  };
  // 从pathInfo中获取路径的总距离和路径段数据
  const { distance, segments } = pathInfo;
  route.distance = distance; // 设置路径的总距离
  // 处理路径的每一段线路
  segments.forEach((s, sIndex) => {
    // 解析每段的线路信息（buslines），如果存在则处理
    const {
      bus: { buslines },
    } = s;
    // 如果该段线路包含线路信息
    if (buslines?.length) {
      // 获取当前线路的目标线路（一般情况下是第一条线路）
      const target = buslines[0];
      // 从lineColors数组中获取该段线路的颜色
      const color = lineColors[sIndex];
      target.color = color; // 设置目标线路的颜色
      route.stations.push(target); // 将目标线路添加到route的stations数组中

      // 遍历该段线路中的每一条线路
      buslines.forEach((b, index) => {
        // 为每条线路创建一个包含起点站、途径站和终点站的对象
        const line = { part: index + 1, partStation: [] };
        // 解构出每条线路的相关信息
        const { type, arrival_stop, departure_stop, name, polyline, via_stops } = b;
        // 将路径信息（包括名称、路径段和坐标数据）添加到paths数组中
        paths.push({
          name, // 线路名称
          part: index + 1, // 线路段序号
          polyline, // 线路的坐标数据
        });
        // 处理“地铁线路”类型的线路
        if (type === '地铁线路') {
          // 设置起点站和终点站
          let arrival = arrival_stop; //终点站信息对象：包含了终点站的id，坐标，名称
          let departure = departure_stop; //始发站信息对象：包含了始发站的id，坐标，名称
          // 如果是最后一段线路，为终点站；否则为换乘站
          arrival.type = sIndex === segments.length - 1 ? '终点站' : '换乘站';
          // 如果是第一段线路，为起点站；否则为换乘站
          departure.type = sIndex === 0 ? '起点站' : '换乘站';
          // 将终点站加入当前线路的partStation数组中
          line.partStation.push(arrival); // 终点站
          // 将途径站加入partStation数组中，设置为“途径站”
          via_stops.forEach(v => {
            v.type = '途径站';
            line.partStation.push(v); // 途径站
          });
          // 将始发站加入当前线路的partStation数组中
          line.partStation.push(departure); // 始发站
          // 为该线路设置名称
          line.name = name;
        }
        // 将处理后的线路站点信息添加到stations数组中
        stations.push(line);
      });
    }
  });
  // 将route对象中的路径信息保存到全局变量routeInfo中
  routeInfo.value = route;
  // 渲染站点和路径信息，不走effectController内部缓存,因为名称不同会影响后续的渲染
  stations.forEach((station, index) => {
    // 从lineColors数组中获取该段线路的颜色
    let color = lineColors[index];
    const { partStation } = station;
    // 遍历每个站点，逐个渲染站点
    partStation.forEach(async p => {
      let { location, name, type } = p;
      // 如果是换乘站，修改站点名称
      name = type === '换乘站' ? name + '(换乘)' : name;
      // 将站点的location（经纬度字符串）转换为经纬度数组
      const positionArr = location.split(',').map(item => Number(item));
      // 创建站点的经纬度对象
      const position = { lng: positionArr[0], lat: positionArr[1] };
      // 渲染站点并设置相应的颜色和名称
      const stationEnt = renderStation(viewer, {
        position,
        name,
        color: type === '换乘站' ? '#e9a526' : color,
      });
      console.log(stationEnt, 'stationEnt');
      // 渲染广告板（站点标注）并设置名称
      const billboard = await renderStationBill(viewer, {
        position,
        name,
        color: type === '换乘站' ? '#e9a526' : color,
        attr: {
          name,
        },
      });
      console.log(billboard, 'billboard');
      // 将站点实体和广告板添加到路径规划实体缓存中
      cacheData.stationEnts.push(stationEnt);
      cacheData.billboards.push(billboard);
    });
  });
  console.log(cacheData, 'cacheData');

  // 遍历路径数组，渲染每条路径
  paths.forEach((path, index) => {
    // 从lineColors数组中获取该路径的颜色
    const color = lineColors[index];
    const {
      polyline: { polyline },
      name,
    } = path;
    // 将路径的polyline字符串分割为多个坐标点
    let positionList = polyline.split(';');
    positionList = positionList.map((pos, index) => {
      const [lng, lat] = pos.split(',').map(item => Number(item));
      return {
        lng: Number(lng),
        lat: Number(lat),
      };
    });
    // 渲染路径（线条）
    const lineEnt = renderLines(viewer, {
      positions: positionList,
      name,
      color,
    });
    // 将路径实体添加到路径规划实体缓存中
    cacheData.lineEnts.push(lineEnt);
  });
  // 调整地图视角，飞行到默认视图位置
  flyToDefaultView(viewer);
};

// 进入规划模式
const enterDesign = async () => {
  if (!Object.keys(pathInfo).length) {
    // 检查是否有起点终点站
    if (startStation.value.length && endStation.value.length) {
      // 如果存在的话，跑服务，填充pathInfo
      const data = await getLineData();
      pathInfo = data;
    } else {
      message.warn('请先选择起点和终点站点');
      return;
    }
  }
  // 如果处于规划模式，就退出
  if (isDesign.value) {
    leaveRouteDesign();
    return;
  }
  // 进入规划模式第一步，隐藏当前地图上所有的元素
  // 我们直接交给图层控制组件完成这一步
  lineData.controlAll(false);
  subLineData.value.forEach(item => {
      const { stationsList } = item;
      stationsList.forEach(station => {
        hideStationByName(station.name, false);
        changeDisplayBillBoard(station.name, false)
      });
  });
  // 第二步，渲染效果
  mapChange();
  isDesign.value = true;
};

// 删除规划实体
const removeActiveEnts = () => {
  removeByCacheData(viewer, cacheData);
  cacheData.billboards = [];
  cacheData.lineEnts = [];
  cacheData.stationEnts = [];
};

// 离开规划模式
const leaveRouteDesign = () => {
  removeActiveEnts();
  lineData.controlAll(true);
  subLineData.value.forEach(item => {
      const { stationsList } = item;
      stationsList.forEach(station => {
        hideStationByName(station.name, true);
        changeDisplayBillBoard(station.name, true)
      });
  });
  isDesign.value = false;
  startStation.value = [];
  endStation.value = [];
  pathInfo = {};
};
</script>

<style scoped>
/* 路径规划样式 */
.route-design-wrapper {
  position: absolute;
  right: 14%;
  top: 5%;
  z-index: 999;
}

.route-design {
  width: 320px;
  height: 170px;
  background-color: rgba(0, 0, 0, 0.6);
  border: 1px solid #885f12;
}

.route-design > .header {
  width: 100%;
  height: 40px;
  color: #fff;
  padding-left: 10px;
  background: rgb(255, 255, 255);
  background-image: linear-gradient(180deg, rgba(255, 255, 255, 1) 9%, rgba(211, 156, 50, 1) 57%);
  -webkit-background-clip: text;
  -webkit-text-fill-color: transparent;
  display: flex;
  align-items: center;
}

.route-design span {
  margin-left: 5px;
}

.content {
  width: 100%;
  height: 110px;
  pointer-events: all;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-around;
  color: #fff;
}

.start-btn {
  width: 80px;
  color: #fff;
  margin-left: 140px;
  background-color: transparent;
  border: 1px solid #885f12;
  font-size: 12px;
  padding: 3px;
  pointer-events: all;
  cursor: pointer;
}

.start-btn:hover {
  background-color: #5c3f096d;
  border: 1px solid #881212;
}
</style>
